package cc.z8g.browser.html

import android.app.Activity
import android.net.Uri
import cc.z8g.browser.BrowserApp
import cc.z8g.browser.R
import cc.z8g.browser.core.BrowserPresenter
import cc.z8g.browser.utils.HttpUtils
import cc.z8g.browser.utils.ThemeUtils
import io.reactivex.rxjava3.core.Single
import java.io.File
import java.util.Collections

/**
 * Factory for the history page.
 */
class WebResFactory(private val activity: Activity, val presenter: BrowserPresenter) : AbsListPageFactory() {

    private fun Int.toColor(): String {
        val string = Integer.toHexString(this)

        return string.substring(2) + string.substring(0, 2)
    }

    override fun buildPage(): Single<String> = TODO()
    override fun getTemplateFilePath(): String = "html/list.html"

    override fun createPageFile(): File = File(BrowserApp.getApplication().filesDir, WEB_RES_FILE_NAME)
    override fun assignTitle(): String = BrowserApp.getApplication().getString(R.string.action_history)
    override fun assignBoxBgColor(): String = ""
    override fun assignBoxTxtColor(): String = ""
    override fun assignBodyBgColor(): String = ThemeUtils.getColor(activity, R.attr.colorPrimary).toColor()

    override fun assignDividerColor(): String = ThemeUtils.getColor(activity, R.attr.autoCompleteBackgroundColor).toColor()

    override fun assignTitleColor(): String = ThemeUtils.getColor(activity, R.attr.autoCompleteTitleColor).toColor()

    override fun assignSubTitleColor(): String = ThemeUtils.getColor(activity, R.attr.autoCompleteUrlColor).toColor()

    override fun assignList(): MutableList<Resource> {
        val tab = presenter.currentTab ?: return Collections.emptyList()
        val webResList = tab.getWebResList()
        if (webResList.isEmpty()) {
            return Collections.emptyList()
        }
        val list = ArrayList<Resource>()

        for (webRes in webResList) {
            val uri = webRes.url
            if (uri.scheme?.equals("file") == true) {
                continue
            }
            if (!"GET".equals(webRes.method, true)) { // POST 请求是真的烦
                continue
            }
            val urlStr = uri.toString()

            val text = uri.buildUpon().clearQuery().build().path.toString()
            val type = guessFileType(uri, HttpUtils.getHeaderField(webRes.requestHeaders, "Accept"))
            val item = Resource(urlStr, text, type, urlStr, type, 0)
            list.add(item)
        }

        Collections.sort(list);
        return list;
    }

    class Resource(
        val href: String,
        val text: String,
        val title: String,
        val imgSrc: String,
        private val type: String,
        var contentLength: Int,
    ) : Comparable<Resource>, Item(href, text, title, imgSrc) {
        private fun compareValueOfType(type: String): Long {
            if (type.isEmpty()) {
                return 0
            }
            if (eq(type, "font")) {
                return -70_000_000_000_000;
            }
            if (eq(type, "message")) {
                return -80_000_000_000_000;
            }
            if (eq(type, "*", "multipart")) {
                return -90_000_000_000_000;
            }
            if (eq(type, "text", ".js", ".css", ".html", ".txt", ".xml", ".pdf")) {
                return -10_000_000_000_000;
            }
            if (eq(type, "application", ".apk", ".zip", ".aar", ".jar", ".rar", ".exe", ".dll")) {
                return +10_000_000_000_000;
            }
            if (eq(type, "image", ".png", ".jpg", ".jpeg", ".webp", ".gif", ".bmp", ".svg", ".psd", ".ai", ".eps", ".tiff", ".ico")) {
                return +20_000_000_000_000;
            }
            if (eq(type, "audio", ".mp3", ".wav", ".flac")) {
                return +40_000_000_000_000;
            }
            if (eq(type, "video", ".mp4", ".webm", ".ogv", ".oga", ".avi", ".flv", ".mov", ".wmv", ".mpg", ".mpeq", ".m3u8")) {
                return +50_000_000_000_000;
            }
            return 0;
        }

        private fun eq(type: String, vararg names: String): Boolean {
            for (name in names) {
                if (type.equals(name, true)) {
                    return true;
                }
            }
            return false;
        }

        override fun compareTo(other: Resource): Int {
            val thisVal = compareValueOfType(this.type) + this.contentLength;
            val otherVal = compareValueOfType(other.type) + other.contentLength;
            return otherVal.compareTo(thisVal)
        }

    }

    private fun guessFileType(uri: Uri, contentType: String?): String {
        val path = uri.path ?: return ""
        val lastIndex = path.lastIndexOf(".")
        if (lastIndex >= 0 && lastIndex < path.length) {
            return path.substring(lastIndex)
        }
        if (contentType != null) {
            return contentType.split("/").get(0)
        }
        return path
    }
}
